#ifndef __SQL_TREE_H__
#define __SQL_TREE_H__

#include "lnstring.h"
#include "sql_func.h"
#include "sql_types.h"
#include "respool.h"
#include <stdio.h>

/*
  hit definition for SQL
  S_HINT_XX
 */

enum
{
  S_HINT_NONE              = 0,
  S_HINT_ORDERED           = 0x01 ,
  S_HINT_RECOMPILE         = 0x02 ,
  S_HINT_JOIN_NESTED_LOOP  = 0x04 ,
  S_HINT_JOIN_INDEX        = 0x08 ,
  S_HINT_JOIN_MERGE        = 0x10 ,
};

typedef unsigned int SQL_HINT_TYPE;

typedef
enum
{
  S_NODE_NONE    = 0      ,
  S_NODE_LIST             ,

  S_NODE_SELECT           ,
  S_NODE_EXPR             ,
  S_NODE_NAME             ,
  S_NODE_VALUE            ,

  S_NODE_CREATE_USER      ,
  S_NODE_CREATE_VIEW      ,
  S_NODE_CREATE_TABLE     ,
  S_NODE_CREATE_INDEX     ,

  S_NODE_ALTER_TABLE      ,
  S_NODE_ALTER_INDEX      ,
  S_NODE_ALTER_USER       ,
  S_NODE_ALTER_CHANGE     ,

  S_NODE_DROP             ,
  S_NODE_RENAME           ,
  S_NODE_UPDATE           ,
  S_NODE_DELETE           ,

  S_NODE_SPEC             , 
  S_NODE_FIELD_DEF        ,

  S_NODE_TYPE_COUNT       ,
}S_NODE_TYPE_DEF;

enum
{
  S_JOIN_INNER = 1,
  S_JOIN_LEFT_OUTER,
  S_JOIN_RIGHT_OUTER,
};

enum
{
  S_SQL_EMPTY   = 1,
  S_SQL_TABLE     ,
  S_SQL_VIEW      ,
  S_SQL_TRIGGER   ,
  S_SQL_PROCEDURE ,
};

enum{
  S_RULE_DELETE_CASCADE     = 0x01,
  S_RULE_DELETE_NO_ACTION   = 0x02,
  S_RULE_DELETE_RESTRICT    = 0x04,
  S_RULE_UPDATE_NO_ACTION   = 0x08,
  S_RULE_UPDATE_RESTRICT    = 0x10,
};

enum
{
  S_CONSTRAINT_NOT_DEFERRABLE     = 0x01,
  S_CONSTRAINT_DEFERRABLE         = 0x02,
  S_CONSTRAINT_INITIALLY_DEFERRED = 0x04,
  S_CONSTRAINT_INITIALLY_IMMEDIATE= 0x08,
};

enum
{
  S_WITH_LEVEL_EMPTY,
  S_WITH_LEVEL_LOCAL,
  S_WITH_LEVEL_CASCADED,
};

struct  SQL_node_t;
struct  SQL_node_vt_t;
struct  SQL_parser_t;
struct  SQL_node_link_t;
struct  SQL_string_list_t;

typedef struct SQL_node_t            SQL_NODE;
typedef struct SQL_node_t          * SQL_NODE_PTR;
typedef struct SQL_node_vt_t       * SQL_NODE_VT_PTR;
typedef struct SQL_parser_t          SQL_PARSER;
typedef struct SQL_parser_t        * SQL_PARSER_PTR;
typedef struct SQL_node_link_t       SQL_NODE_LINK;
typedef struct SQL_node_link_t     * SQL_NODE_LINK_PTR;
typedef struct SQL_string_list_t     SQL_STRING_LIST;

extern  SQL_NODE_VT_PTR      SQL_node_vt_list[S_NODE_TYPE_COUNT];

struct SQL_node_vt_t
{
  int (*close)(SQL_NODE_PTR);
  int (*dump)(SQL_NODE_PTR node, LN_STRING_PTR lines,const char* name, int dep);
};


/* detail definition for each */
struct SQL_node_link_t
{
  struct SQL_node_link_t * next;
  SQL_NODE_PTR data;
};

struct SQL_node_list_t
{
  SQL_NODE_LINK_PTR head;
  SQL_NODE_LINK_PTR last;
};

struct SQL_node_name_t
{
  struct SQL_node_name_t * next;
  const char * name;
  const char * prefix;
  int  flag;
};

struct SQL_node_create_table_t
{
  struct SQL_node_name_t *  name;
  SQL_NODE_PTR  attr_def_list;
  unsigned int  hints;
};

struct SQL_node_field_def_t
{
  const char* name;
  LN_INT64    type;
};

struct SQL_node_table_spec_t
{
  const char* as_name;
  SQL_NODE_PTR spec;
};

struct SQL_node_select_t
{
    SQL_HINT_TYPE hints;
    unsigned      distinct;
    SQL_NODE_PTR  spec_list;
    SQL_NODE_PTR  where_clause;
    SQL_NODE_PTR  select_list;

    SQL_NODE_PTR  order_by;
    SQL_NODE_PTR  group_by;
    SQL_NODE_PTR  having;
    struct SQL_node_name_t* to_param;
    SQL_NODE_PTR  using_index;
};

struct SQL_node_update_t
{
  SQL_HINT_TYPE hints;
  struct SQL_node_name_t * table_name;
  const char*   as_id;
  SQL_NODE_PTR  update_list;
  SQL_NODE_PTR  where_clause;
  SQL_NODE_PTR  using_index;
};

struct SQL_node_expr_t
{
  S_FUNC_TYPE_DEF op;
  SQL_NODE_PTR p1;
  SQL_NODE_PTR p2;
  SQL_NODE_PTR p3;
  const char*  as_name;
  int     asc_flag : 1;
};

struct SQL_node_t
{
  S_NODE_TYPE_DEF  type;

  union {
    LN_VARIANT                            value;
    struct SQL_node_list_t                list;
    struct SQL_node_create_table_t        create_table;
    struct SQL_node_select_t              select;
    struct SQL_node_expr_t                expr;
    struct SQL_node_name_t                name;
    struct SQL_node_update_t              update;
    struct SQL_node_field_def_t           field_def;
    struct SQL_node_table_spec_t          table_spec;
  }dt;
};

struct SQL_parser_t
{
  LN_THREAD_PTR thrd;
  int    line;
  int    column;

  const char * buffer;
  const char * buffer_end;
  const char * buffer_current;
  int          buffer_size;

  respool  mempool;
  char     mempool_buffer[4096];
  SQL_NODE_PTR statements;
};

int   sql_parser_init  (SQL_PARSER_PTR parser);
void  sql_parser_close (SQL_PARSER_PTR parser);

extern  SQL_PARSER_PTR SQL_this_parser;

struct function_map
{
  const char*     name;
  S_FUNC_TYPE_DEF op;
  void*           func;
};

struct SQL_string_list_t
{
  int size;
  char** list;
};

struct SQL_node_name_t * sql_new_name ();
SQL_NODE_PTR    sql_new_node ( S_NODE_TYPE_DEF ty);
SQL_NODE_PTR    sql_new_list_node_and_add (SQL_NODE_PTR p);
SQL_NODE_PTR    sql_add_node_to_list (SQL_NODE_PTR lst, SQL_NODE_PTR n);

SQL_HINT_TYPE   sql_read_hint ( const char * comment);
LN_INT64        sql_read_unsigned_dec ( const char * s);

SQL_NODE_PTR    sql_make_node_list ( SQL_NODE_PTR p1, SQL_NODE_PTR p2);
SQL_NODE_PTR    sql_make_expression (S_FUNC_TYPE_DEF op, SQL_NODE_PTR p1, SQL_NODE_PTR p2, SQL_NODE_PTR p3);

SQL_NODE_PTR    sql_parser (SQL_PARSER_PTR parser, const char* s,int size);

char*           sql_strdup(const char* s);
char*           sql_strcat(const char* s1, const char* s2, const char* s3);
int             sql_string_list_add (SQL_STRING_LIST *list, const char* s);

#endif,

